package cn.xspace.library.util;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;

import com.ctnq.util.EncryptUtil;
import com.google.gson.Gson;
import com.xspace.android.xafcommon.R;
import com.xspace.android.xafcommon.appliction.BaseApplication;
import com.xspace.android.xafcommon.been.BaseReturnBean;
import com.xspace.android.xafcommon.network.exception.HttpException;
import com.xspace.android.xafcommon.util.ErrorCode;
import com.xspace.android.xafcommon.util.JSONUtil;
import com.xspace.android.xafcommon.util.LogUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

import static android.content.Context.MODE_PRIVATE;

/**
 * Created by liuchen on 2016/10/18.
 */
public class OkHttpManager {

    private static final String TAG = "OkHttpManager";
    /**
     * 静态实例
     */
    private static OkHttpManager sOkHttpManager;

    /**
     * okhttpclient实例
     */
    private static OkHttpClient mClient;

    /**
     * 因为我们请求数据一般都是子线程中请求，在这里我们使用了handler
     */
    private Handler mHandler;
    static final int DISK_CACHE_SIZE = 50 * 1024 * 1024; // 50MB

    /**
     * 构造方法
     */
    private OkHttpManager() {

        File cacheDir = new File(BaseApplication.mInstance.getCacheDir(), "http");
        Cache cache = new Cache(cacheDir, DISK_CACHE_SIZE);

        mClient = new OkHttpClient()
                .newBuilder()
                .connectTimeout(1, TimeUnit.MINUTES) //设置连接超时
                .readTimeout(1, TimeUnit.MINUTES) //设置读取超时
                .writeTimeout(1, TimeUnit.MINUTES) //设置写入超时
                .cache(cache)
                .build();
        /**
         * 如果是用的3.0之前的版本  使用以下直接设置连接超时.读取超时，写入超时
         */

        //client.setConnectTimeout(10, TimeUnit.SECONDS);
        //client.setWriteTimeout(10, TimeUnit.SECONDS);
        //client.setReadTimeout(30, TimeUnit.SECONDS);


        /**
         * 初始化handler
         */
        mHandler = new Handler(Looper.getMainLooper());
    }


    /**
     * 单例模式  获取OkHttpManager实例
     *
     * @return
     */
    public static synchronized OkHttpManager getInstance() {

        if (sOkHttpManager == null) {
            sOkHttpManager = new OkHttpManager();
        }
        return sOkHttpManager;
    }

    /**
     * 发送格式为map的请求
     *
     * @param url
     * @param params
     * @return
     */
    public Observable<String> commonRequestPost(final String url, final Map<String, Object> params) {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(final Subscriber<? super String> subscriber) {
                LogUtil.i(TAG, "params>>>>" + params.toString());
                LogUtil.i(TAG, "url>>>>" + url);
                String jsonStr = new Gson().toJson(params);
                LogUtil.d(TAG, "jsonStr>>>>" + jsonStr);
                FormBody.Builder req = new FormBody.Builder();
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    req.add(entry.getKey(), entry.getValue().toString());
                }

                final Request request = new Request.Builder().url(url).post(req.build()).build();
                mClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        if (e != null) {
                            e.printStackTrace();
                        } else {
                            LogUtil.d(TAG, "onFailure e == null");
                        }
                        LogUtil.d(TAG, "onFailure ");
                        subscriber.onError(new HttpException(BaseApplication.mInstance.getResources().getString(R
                                .string.network_error), HttpException.NETWORK_ERROW));
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String result = response.body().string();
                        LogUtil.d(TAG, "wubaojie>>>onResponse: result:" + result);
                        if (response.isSuccessful()) {
                            LogUtil.d("成功");
                        } else {
                            LogUtil.d("失败");
                        }
                        subscriber.onNext(result);
                    }
                });
            }
        });
    }

    /**
     * 发送格式为json的请求
     *
     * @param url
     * @param params
     * @return
     */
    public Observable<String> commonJsonPost(final String url, final Map<String, Object> params) {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(final Subscriber<? super String> subscriber) {
                LogUtil.i(TAG, "params>>>>" + params.toString());
                LogUtil.i(TAG, "url>>>>" + url);
                String jsonStr = new Gson().toJson(params);
                LogUtil.v(TAG, "jsonStr>>>>" + jsonStr);
                MediaType JSON = MediaType.parse("application/json; charset=utf-8");
                RequestBody body = RequestBody.create(JSON, jsonStr);
                final Request request = new Request.Builder().url(url).post(body).build();
                mClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        if (e != null) {
                            e.printStackTrace();
                        } else {
                            LogUtil.d(TAG, "onFailure e == null");
                        }
                        LogUtil.d(TAG, "onFailure ");
                        subscriber.onError(new HttpException(BaseApplication.mInstance.getResources().getString(R
                                .string.network_error), HttpException.NETWORK_ERROW));
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String result = response.body().string();
                        LogUtil.d(TAG, "wubaojie>>>onResponse: result:" + result);
                        if (response.isSuccessful()) {
                            LogUtil.d("成功");
                        } else {
                            LogUtil.d("失败");
                        }
                        subscriber.onNext(result);
                    }
                });
            }
        });
    }

    public Observable<BaseReturnBean>  commonJsonEncryptRequest(final String url, final String params) {
        return Observable.create(new Observable.OnSubscribe<BaseReturnBean>() {
            @Override
            public void call(final Subscriber<? super BaseReturnBean> subscriber) {
                LogUtil.i(TAG, "params>>>>" + params);
                LogUtil.i(TAG, "url>>>>" + url);
                EncryptBean encryptBean = new EncryptBean(params);
                String sendData = encryptBean.sendData(encryptBean);
                LogUtil.v(TAG, "sendData>>>" + sendData);
                MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");
                RequestBody body = RequestBody.create(JSON, sendData);
                final Request request = new Request.Builder().url(url).post(body).build();
                mClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        if (e != null) {
                            e.printStackTrace();
                        } else {
                            LogUtil.d(TAG, "onFailure e == null");
                        }
                        LogUtil.d(TAG, "onFailure ");
                        subscriber.onError(new HttpException(BaseApplication.mInstance.getResources().getString(R
                                .string.network_error), HttpException.NETWORK_ERROW));
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String resultEn = null;
                        try {
                            resultEn = response.body().string();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        LogUtil.v(TAG, "  result begin>>>" + resultEn); //未解密之前的原始结果
                        String result = null;
                        try {
                            result = EncryptUtil.getInstance().getDecryptData(resultEn);
                        } catch (Exception e) {
                            e.printStackTrace();
                            subscriber.onError(new HttpException(HttpException.DATA_ENCRYPT_FAIL, HttpException
                                    .ENCRYPT_ERROR));
                        }
                        LogUtil.i(TAG, "url :" + url + "\nparams :" + params + "\n返回结果 :" + result);
                        final BaseReturnBean returnBean = new BaseReturnBean();
                        JSONObject dataJSon = null;
                        try {
                            JSONObject proDataJSON = new JSONObject(result);
                            String proDataStr = proDataJSON.optString("pro_data");
                            dataJSon = new JSONObject(proDataStr);
                            String code = dataJSon.optString("code");
                            String desc = dataJSon.optString("desc");
                            String data = "";
                            if (dataJSon.has("data")) {
                                data = dataJSon.optString("data");
                            } else if (dataJSon.has("msgList")) {
                                data = dataJSon.optString("msgList");
                            } else if (dataJSon.has("msg")) {
                                data = dataJSon.optString("msg");
                            }
                            returnBean.code = code;
                            returnBean.data = data;
                            returnBean.desc = desc;
                            LogUtil.d(TAG, "returnBean.data>>" + data);
                            LogUtil.d("returnBean.code>>" + code);
                            LogUtil.d("returnBean.desc>>" + desc);
                            subscriber.onNext(returnBean);
                            subscriber.onCompleted();
                        } catch (JSONException e) {
                            e.printStackTrace();
                            subscriber.onError(new HttpException(HttpException.PARSE_JSON_ERROR,
                                    HttpException.JSON_ERROR));
                        }
                    }
                });
            }
        });
    }

    public Observable<BaseReturnBean> commonEncryptRequest(final String url, final Map<String, Object> params) {
        return Observable.create(new Observable.OnSubscribe<BaseReturnBean>() {
            @Override
            public void call(final Subscriber<? super BaseReturnBean> subscriber) {
                final String sendJson = JSONUtil.parseMapToJson(params);
                LogUtil.i(TAG, "params>>>>" + params);
                LogUtil.i(TAG, "url>>>>" + url);
                EncryptBean encryptBean = new EncryptBean(params);
                String sendData = encryptBean.sendData(encryptBean);
                LogUtil.v(TAG, "sendData>>>" + sendData);
                MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");
                RequestBody body = RequestBody.create(JSON, sendData);
                final Request request = new Request.Builder().url(url).post(body).build();
                mClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        if (e != null) {
                            e.printStackTrace();
                        } else {
                            LogUtil.d(TAG, "onFailure e == null");
                        }
                        LogUtil.d(TAG, "onFailure ");
                        subscriber.onError(new HttpException(BaseApplication.mInstance.getResources().getString(R
                                .string.network_error), HttpException.NETWORK_ERROW));
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String resultEn = null;
                        try {
                            resultEn = response.body().string();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        LogUtil.v(TAG, "  result begin>>>" + resultEn); //未解密之前的原始结果
                        String result = null;
                        try {
                            result = EncryptUtil.getInstance().getDecryptData(resultEn);
                        } catch (Exception e) {
                            e.printStackTrace();
                            subscriber.onError(new HttpException(HttpException.DATA_ENCRYPT_FAIL, HttpException
                                    .ENCRYPT_ERROR));
                        }
                        LogUtil.i(TAG, "url :" + url + "\nparams :" + sendJson + "\n返回结果 :" + result);
                        final BaseReturnBean returnBean = new BaseReturnBean();
                        JSONObject dataJSon;
                        try {
                            JSONObject proDataJSON = new JSONObject(result);
                            String proDataStr = proDataJSON.optString("pro_data");
                            dataJSon = new JSONObject(proDataStr);
                            String code = dataJSon.optString("code");
                            String desc = dataJSon.optString("desc");
                            String data = "";
                            if (dataJSon.has("data")) {
                                data = dataJSon.optString("data");
                            } else if (dataJSon.has("msgList")) {
                                data = dataJSon.optString("msgList");
                            } else if (dataJSon.has("msg")) {
                                data = dataJSon.optString("msg");
                            }
                            returnBean.code = code;
                            returnBean.data = data;
                            returnBean.desc = desc;
                            LogUtil.d(TAG, "returnBean.data>>" + data);
                            LogUtil.d("returnBean.code>>" + code);
                            LogUtil.d("returnBean.desc>>" + desc);
                            subscriber.onNext(returnBean);
                            subscriber.onCompleted();
                        } catch (JSONException e) {
                            e.printStackTrace();
                            subscriber.onError(new HttpException(HttpException.PARSE_JSON_ERROR,
                                    HttpException.JSON_ERROR));
                        }
                    }
                });
            }
        });
    }

    /**
     * 共同的请求方法，返回一个Observable对象，Okhttp跟Rx配合
     *
     * @param url
     * @param params
     * @return
     */
    public Observable<BaseReturnBean> commonRequest(final String url, final Map<String, Object> params) {
        return Observable.create(new Observable.OnSubscribe<BaseReturnBean>() {
            @Override
            public void call(final Subscriber<? super BaseReturnBean> subscriber) {
                final String sendJson = JSONUtil.parseMapToJson(params);
                LogUtil.i(TAG, "params>>>>" + sendJson);
                LogUtil.i(TAG, "url>>>>" + url);
                EncryptBean encryptBean = new EncryptBean(params);
                String sendData = encryptBean.sendData(encryptBean);
                LogUtil.v(TAG, "sendData>>>" + sendData);
                MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");
                RequestBody body = RequestBody.create(JSON, sendData);
                //结果返回
                final Request request = new Request.Builder().url(url).post(body).build();
                mClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        if (e != null) {
                            e.printStackTrace();
                        } else {
                            LogUtil.d(TAG, "onFailure e == null");
                        }
                        LogUtil.d(TAG, "onFailure ");
//                        T.show(MyApplication.get(), MyApplication.get().getResources().getString(R.string
// .network_error), Toast.LENGTH_SHORT);
//                        subscriber.onError(new Exception(e));
                        subscriber.onError(new HttpException(HttpException.NET_WORK_ERROR,
                                HttpException.NETWORK_ERROW));
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String resultEn = null;
                        try {
                            resultEn = response.body().string();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        LogUtil.v(TAG, "  result begin>>>" + resultEn); //未解密之前的原始结果
                        String result = null;
                        try {
                            result = EncryptUtil.getInstance().getDecryptData(resultEn);
                        } catch (Exception e) {
                            e.printStackTrace();
                            subscriber.onError(new HttpException(HttpException.DATA_ENCRYPT_FAIL, HttpException
                                    .ENCRYPT_ERROR));
                        }
                        LogUtil.i(TAG, "url :" + url + "\nparams :" + sendJson + "\n返回结果 :" + result);
                        final BaseReturnBean returnBean = new BaseReturnBean();
                        JSONObject proDataJSON = null;
                        JSONObject dataJSon = null;
                        try {
                            proDataJSON = new JSONObject(result);
                            String proDataStr = proDataJSON.optString("pro_data");
                            dataJSon = new JSONObject(proDataStr);
                            String code = dataJSon.optString("code");
                            String desc = dataJSon.optString("desc");
                            String data = "";
                            if (dataJSon.has("data")) {
                                data = dataJSon.optString("data");
                            } else if (dataJSon.has("msgList")) {
                                data = dataJSon.optString("msgList");
                            } else if (dataJSon.has("msg")) {
                                data = dataJSon.optString("msg");
                            }
                            LogUtil.d(TAG, "returnBean.data>>" + data);
                            returnBean.code = code;
                            returnBean.data = data;
                            returnBean.desc = desc;
                        } catch (JSONException e) {
                            e.printStackTrace();
                            subscriber.onError(new HttpException(HttpException.PARSE_JSON_ERROR, HttpException
                                    .JSON_ERROR));
                        }
                        LogUtil.d("returnBean.code>>" + returnBean.code);
                        LogUtil.d("returnBean.desc>>" + returnBean.desc);

                        if (!TextUtils.isEmpty(returnBean.code) && returnBean.code.endsWith(ErrorCode
                                .SUCCESS_CODE_SUFFIX) || "0".equals(returnBean.code)) {
                            LogUtil.d("1");
                            subscriber.onNext(returnBean);
                            subscriber.onCompleted();
                        } else {
                            LogUtil.d("2");
                            subscriber.onError(new HttpException(dataJSon.optString("desc"), HttpException
                                    .OTHER_ERROR));
                        }
                    }
                });
            }
        });
    }
    //网络下载RX

    public Observable<Response> downloadFile(final String url) {
        if (TextUtils.isEmpty(url)) {
            Log.d(TAG, "下载地址不能为空");
            return null;
        }
        return Observable.create(new Observable.OnSubscribe<Response>() {
            @Override
            public void call(final Subscriber<? super Response> subscriber) {
                final Request request = new Request.Builder().url(url).build();
                mClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        subscriber.onError(e);
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        subscriber.onNext(response);
                    }
                });
            }
        });
    }

    public Observable<BaseReturnBean> commonRequestWithoutEncrypt(final String url, final Map<String, Object> params) {
        return Observable.create(new Observable.OnSubscribe<BaseReturnBean>() {
            @Override
            public void call(final Subscriber<? super BaseReturnBean> subscriber) {
                LogUtil.d(TAG, "params>>>>" + params.toString());
                LogUtil.d(TAG, "url>>>>" + url);
//                String sendData = params.toString();
                final String sendData = JSONUtil.parseMapToJson(params);
//                LogUtil.d(TAG, "sendData>>>" + sendData);
                MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");
                RequestBody body = RequestBody.create(JSON, sendData);
                //结果返回
                final Request request = new Request.Builder().url(url).post(body).build();
                mClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        if (e != null) {
                            e.printStackTrace();
                        } else {
                            LogUtil.d(TAG, "onFailure e == null");
                        }
                        LogUtil.d(TAG, "onFailure ");
//                        T.show(MyApplication.get(), MyApplication.get().getResources().getString(R.string
// .network_error), Toast.LENGTH_SHORT);
//                        subscriber.onError(new Exception(e));
                        subscriber.onError(new HttpException(BaseApplication.mInstance.getResources().getString(R
                                .string.network_error),
                                HttpException.NETWORK_ERROW));
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String result = null;
                        try {
                            result = response.body().string();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
//                        LogUtil.d(TAG, "  result begin>>>" + result); //未解密之前的原始结果
//                        String result = null;
//                        try {
//                            result = EncryptUtil.getInstance().getDecryptData(resultEn);
//                        } catch (Exception e) {
//                            e.printStackTrace();
//                            subscriber.onError(new HttpException(HttpException.DATA_ENCRYPT_FAIL, HttpException
// .ENCRYPT_ERROR));
//                        }
                        LogUtil.d(TAG, "url :" + url + " parem :" + sendData + "  返回结果 :" + result);
                        final BaseReturnBean returnBean = new BaseReturnBean();

                        JSONObject dataJSon = null;
                        try {
                            dataJSon = new JSONObject(result);
                            String code = dataJSon.optString("code");
                            String desc = dataJSon.optString("desc");
                            String data = "";
                            if (dataJSon.has("msgList")) {
                                data = dataJSon.optString("msgList");
                            } else if (dataJSon.has("msg")) {
                                data = dataJSon.optString("msg");
                            } else if (dataJSon.has("data")) {
                                data = dataJSon.optString("data");
                            } else {
                                data = result;
                            }
                            LogUtil.d("prodata>>>>" + data);
                            returnBean.code = code;
                            returnBean.data = data;
                            returnBean.desc = desc;
                        } catch (JSONException e) {
                            e.printStackTrace();
                            try {
                                subscriber.onError(new HttpException(dataJSon.optString("desc"), HttpException
                                        .JSON_ERROR));
                            } catch (Exception e2) {
                                e2.getMessage();
                                subscriber.onError(new HttpException("error", HttpException.JSON_ERROR));
                            }
                        }
                        LogUtil.d("returnBean.code>>" + returnBean.code);
                        LogUtil.d("returnBean.desc>>" + returnBean.desc);

                        if (!TextUtils.isEmpty(returnBean.code) && returnBean.code.endsWith(ErrorCode
                                .SUCCESS_CODE_SUFFIX) || "0".equals(returnBean.code)) {
                            LogUtil.d("1");
                            subscriber.onNext(returnBean);

                        } else {
                            LogUtil.d("2");
                            if ("-1".equals(dataJSon.optString("code"))) {
                                subscriber.onError(new HttpException("-1", HttpException
                                        .OTHER_ERROR));
                            } else {
                                subscriber.onError(new HttpException(dataJSon.optString("desc"), HttpException
                                        .OTHER_ERROR));
                            }
                        }
                        subscriber.onCompleted();
                    }
                });
            }
        });
    }

//    public Observable<BaseReturnBean> commonRequestNotEncryp(final String url, final Map<String, Object> params) {
//        return Observable.create(new Observable.OnSubscribe<BaseReturnBean>() {
//            @Override
//            public void call(final Subscriber<? super BaseReturnBean> subscriber) {
//                LogUtil.d(TAG, "params>>>>" + params.toString());
//                LogUtil.d(TAG, "url>>>>" + url);
//                String sendData = new Gson().toJson(params);
//                LogUtil.d(TAG, "sendData>>>" + sendData);
//                MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");
//                RequestBody body = RequestBody.create(JSON, sendData);
//                //结果返回
//                final Request request = new Request.Builder().url(url).post(body).build();
//                mClient.newCall(request).enqueue(new Callback() {
//                    @Override
//                    public void onFailure(Call call, IOException e) {
//                        if (e != null) {
//                            e.printStackTrace();
//                        } else {
//                            LogUtil.d(TAG, "onFailure e == null");
//                        }
//                        LogUtil.d(TAG, "onFailure ");
////                        T.show(MyApplication.get(), MyApplication.get().getResources().getString(R.string
// .network_error), Toast.LENGTH_SHORT);
////                        subscriber.onError(new Exception(e));
//                        subscriber.onError(new HttpException(MyApplication.get().getResources().getString(R.string
// .network_error),
//                                HttpException.NETWORK_ERROW));
//                    }
//
//                    @Override
//                    public void onResponse(Call call, Response response) throws IOException {
//                        String resultEn = null;
//                        try {
//                            resultEn = response.body().string();
//                        } catch (IOException e) {
//                            e.printStackTrace();
//                        }
//                        LogUtil.d(TAG, "  result begin>>>" + resultEn);
//                        LogUtil.d(TAG, "url :" + url + " parem :" + params.toString() + "  返回结果 :" + resultEn);
//                        final BaseReturnBean returnBean = new BaseReturnBean();
//                        JSONObject proDataJSON = null;
//                        JSONObject dataJSon = null;
//                        try {
//                            proDataJSON = new JSONObject(resultEn);
//                            String proDataStr = proDataJSON.optString("pro_data");
//                            dataJSon = new JSONObject(proDataStr);
//                            String code = dataJSon.optString("code");
//                            String desc = dataJSon.optString("desc");
//                            String data = dataJSon.optString("data");
//                            LogUtil.d("prodata>>>>" + data);
//                            returnBean.code = code;
//                            returnBean.data = data;
//                            returnBean.desc = desc;
//                        } catch (JSONException e) {
//                            e.printStackTrace();
//                            subscriber.onError(new HttpException(dataJSon.optString("desc"), HttpException
// .JSON_ERROR));
//                        }
//                        LogUtil.d("returnBean.code>>" + returnBean.code);
//                        LogUtil.d("returnBean.desc>>" + returnBean.desc);
//
//                        if (!TextUtils.isEmpty(returnBean.code) && returnBean.code.endsWith(ErrorCode
// .SUCCESS_CODE_SUFFIX)) {
//                            LogUtil.d("1");
//                            subscriber.onNext(returnBean);
//
//                        } else {
//                            LogUtil.d("2");
//                            subscriber.onError(new HttpException(dataJSon.optString("desc"), HttpException
// .OTHER_ERROR));
//                        }
//                    }
//                });
//            }
//        });
//    }
    //-------------------------同步的方式请求数据--------------------------

    /**
     * 对外提供的get方法,同步的方式
     *
     * @param url 传入的地址
     * @return
     */
    public Response getSync(String url) {

        return inner_getSync(url);
    }

    /**
     * GET方式请求的内部逻辑处理方式，同步的方式
     *
     * @param url
     * @return
     */
    private Response inner_getSync(String url) {
        Request request = new Request.Builder().url(url).build();
        Response response = null;
        try {
            //同步请求返回的是response对象
            response = mClient.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    /**
     * 对外提供的同步获取String的方法
     *
     * @param url
     * @return
     */
    public String getSyncString(String url) {
        return inner_getSyncString(url);
    }


    /**
     * 同步方法
     */
    private String inner_getSyncString(String url) {
        String result = null;
        try {
            /**
             * 把取得到的结果转为字符串，这里最好用string()
             */
            result = inner_getSync(url).body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    //-------------------------异步的方式请求数据--------------------------
    public static void getAsync(String url, DataCallBack callBack) {
        getInstance().inner_getAsync(url, callBack);
    }

    /**
     * 内部逻辑请求的方法
     *
     * @param url
     * @param callBack
     * @return
     */
    private void inner_getAsync(String url, final DataCallBack callBack) {
        final Request request = new Request.Builder().url(url).build();

        mClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                deliverDataFailure(request, e, callBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = null;
                try {
                    result = response.body().string();
                } catch (IOException e) {
                    deliverDataFailure(request, e, callBack);
                }
                deliverDataSuccess(result, callBack);
            }
        });
    }


    /**
     * 分发失败的时候调用
     *
     * @param request
     * @param e
     * @param callBack
     */
    private void deliverDataFailure(final Request request, final Exception e, final DataCallBack callBack) {
        /**
         * 在这里使用异步处理
         */
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (callBack != null) {
                    callBack.requestFailure(request, e);
                }
            }
        });
    }


    /**
     * 分发成功的时候调用
     *
     * @param result
     * @param callBack
     */
    private void deliverDataSuccess(final String result, final DataCallBack callBack) {
        final BaseReturnBean returnBean = new BaseReturnBean();
        JSONObject proDataJSON = null;
        JSONObject dataJSon = null;
        try {
            proDataJSON = new JSONObject(result);
            String proDataStr = proDataJSON.optString("pro_data");
            dataJSon = new JSONObject(proDataStr);
            String code = dataJSon.optString("code");
            String desc = dataJSon.optString("desc");
            String data = dataJSon.optString("data");
            returnBean.code = code;
            returnBean.data = data;
            returnBean.desc = desc;
            /**
             * 在这里使用异步线程处理
             */
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (callBack != null) {
                        try {
                            callBack.requestSuccess(returnBean);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            });
        } catch (JSONException e) {
            e.printStackTrace();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (callBack != null) {
                        try {
                            callBack.requestSuccess(result);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            });

        }

    }

    private void deliverDataSuccessFile(final String result, final DataCallBack callBack) {

        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (callBack != null) {
                    try {
                        callBack.requestSuccess(result);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    /**
     * 数据回调接口
     */
    public interface DataCallBack {
        void requestBefore();

        void requestFailure(Request request, Exception e);

        void requestSuccess(BaseReturnBean result) throws Exception;

        void requestSuccess(String result) throws Exception;

    }

    //-------------------------提交表单--------------------------

    public void inner_postAsync(String url, Map<String, Object> params, final DataCallBack callBack) {
        LogUtil.d(TAG, "params == null ?");
        LogUtil.d(TAG, params == null ? "true" : "false");
        LogUtil.d(TAG, "inner_postAsync");
        LogUtil.d(TAG, "params>>>>" + params.toString());
        if (params == null) {
            params = new HashMap<>();
        }
        EncryptBean encryptBean = new EncryptBean(params);
        String sendData = encryptBean.sendData(encryptBean);
        LogUtil.d(TAG, "sendData>>>" + sendData);
        MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");
        RequestBody body = RequestBody.create(JSON, sendData);
        //结果返回
        final Request request = new Request.Builder().url(url).post(body).build();
        if (callBack != null) {
            callBack.requestBefore();
        }

        mClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                LogUtil.d(TAG, "onFailure ");
                if (e != null) {
                    e.printStackTrace();
                } else {
                    LogUtil.d(TAG, "onFailure e == null");
                }
                deliverDataFailure(request, e, callBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                LogUtil.d(TAG, "response");
                String resultEn = response.body().string();
                String result = null;
                try {
                    result = EncryptUtil.getInstance().getDecryptData(resultEn);
                } catch (Exception e) {
                    e.printStackTrace();
                    deliverDataFailure(request, e, callBack);
                }
                LogUtil.d(TAG, "result 返回结果" + result);
                deliverDataSuccess(result, callBack);
            }
        });
    }


    //-------------------------文件下载--------------------------
    public void downloadAsync(String url, String desDir, String fileName, DataCallBack callBack) {
        inner_downloadAsync(url, desDir, fileName, callBack);
    }

    //网络下载RX
    public Observable<String> downloadFileRx(final String url, final String desDir) {
        if (TextUtils.isEmpty(url)) {
            LogUtil.d(TAG, "下载地址不能为空");
            return null;
        }
        return Observable.create(new Observable.OnSubscribe<String>() {

            @Override
            public void call(final Subscriber<? super String> subscriber) {
                final Request request = new Request.Builder().url(url).build();
                mClient.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        subscriber.onError(new HttpException(BaseApplication.mInstance.getResources().getString(R
                                .string.network_error),
                                HttpException.NETWORK_ERROW));
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        File fileDie = new File(desDir);
                        if (fileDie.exists()) {
                            LogUtil.d(TAG, "目录文件存在");
                        } else {
                            fileDie.mkdirs();
                            LogUtil.d(TAG, "目录文件不存在");
                        }
                        /**
                         * 在这里进行文件的下载处理
                         */
                        InputStream inputStream = null;
                        FileOutputStream fileOutputStream = null;
                        try {
                            //文件名和目标地址
                            File file = new File(desDir, getFileName(url));
                            //把请求回来的response对象装换为字节流
                            inputStream = response.body().byteStream();
                            fileOutputStream = new FileOutputStream(file);
                            int len = 0;
                            byte[] bytes = new byte[2048];
                            //循环读取数据
                            while ((len = inputStream.read(bytes)) != -1) {
                                fileOutputStream.write(bytes, 0, len);
                            }
                            //关闭文件输出流
                            fileOutputStream.flush();
                            //调用分发数据成功的方法
                            subscriber.onNext(file.getAbsolutePath());
                        } catch (IOException e) {
                            //如果失败，调用此方法
                            subscriber.onError(new HttpException(BaseApplication.mInstance.getResources().getString(R
                                    .string.IO_error),
                                    HttpException.IO_ERROR));
                            e.printStackTrace();
                        } finally {
                            if (inputStream != null) {
                                inputStream.close();
                            }
                            if (fileOutputStream != null) {
                                fileOutputStream.close();
                            }
                        }
                    }
                });
            }
        });
    }

    /**
     * 下载文件的内部逻辑处理类
     *
     * @param url      下载地址
     * @param desDir   目标地址
     * @param callBack
     */

    private void inner_downloadAsync(final String url, final String desDir, final String fileName, final DataCallBack
            callBack) {
        if (TextUtils.isEmpty(url)) {
            LogUtil.d(TAG, "下载地址不能为空");
            return;
        }
        LogUtil.d(TAG, "download url " + url);
        final Request request = new Request.Builder().url(url).build();
        mClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                deliverDataFailure(request, e, callBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                File fileDie = new File(desDir);
                if (fileDie.exists()) {
                    LogUtil.d(TAG, "目录文件存在");
                } else {
                    fileDie.mkdirs();
                    LogUtil.d(TAG, "目录文件不存在");
                }
                /**
                 * 在这里进行文件的下载处理
                 */
                InputStream inputStream = null;
                FileOutputStream fileOutputStream = null;
                try {
                    //文件名和目标地址
                    File file = new File(desDir, TextUtils.isEmpty(fileName) ? getFileName(url) : fileName);
                    //把请求回来的response对象装换为字节流
                    inputStream = response.body().byteStream();
                    fileOutputStream = new FileOutputStream(file);
                    int len = 0;
                    byte[] bytes = new byte[2048];
                    //循环读取数据
                    while ((len = inputStream.read(bytes)) != -1) {
                        fileOutputStream.write(bytes, 0, len);
                    }
                    //关闭文件输出流
                    fileOutputStream.flush();
                    //调用分发数据成功的方法
                    deliverDataSuccessFile(file.getAbsolutePath(), callBack);
                } catch (IOException e) {
                    //如果失败，调用此方法
                    deliverDataFailure(request, e, callBack);
                    e.printStackTrace();
                } finally {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                    if (fileOutputStream != null) {
                        fileOutputStream.close();
                    }

                }
            }

        });
    }

    /**
     * 根据文件url获取文件的路径名字
     *
     * @param url
     * @return
     */
    private String getFileName(String url) {
        int separatorIndex = url.lastIndexOf("/");
        String path = (separatorIndex < 0) ? url : url.substring(separatorIndex + 1, url.length());
        return path;
    }

    private void upLoadFile(String actionUrl, Map<String, Object> paramsMap) {

    }

    /**
     * @param actionUrl 接口地址
     * @param paramsMap 数据map
     * @param listener  监听进度
     */
    public void upLoadFile(String actionUrl, Map<String, Object> paramsMap, final ProgressListener listener, final
    DataCallBack callBack) {
        LogUtil.d(TAG, "upLoadFile");
        LogUtil.d(TAG, "upLoadFile>>>" + paramsMap.toString());
        MultipartBody.Builder builder = new MultipartBody.Builder();
        //设置类型
        builder.setType(MultipartBody.FORM);
        StringBuffer msgContentSb = new StringBuffer();
        msgContentSb.append(actionUrl + "?");

        //追加参数
        for (String key : paramsMap.keySet()) {
            LogUtil.d(TAG, "upLoadFile key   " + key);
            Object object = paramsMap.get(key);
            if (!(object instanceof File)) {
                LogUtil.d(TAG, "upLoadFile value    " + object.toString());
                builder.addFormDataPart(key, object.toString());
                msgContentSb.append(key + " = " + object.toString() + "&");
            } else {
                File file = (File) object;
                LogUtil.d(TAG, "upLoadFile file " + file.getAbsolutePath());
                builder.addFormDataPart(key, file.getName(), createCustomRequestBody(MediaType.parse
                        ("application/octet-stream"), file, listener));
            }
        }

        if (msgContentSb.lastIndexOf("&") != -1) {
            msgContentSb.deleteCharAt(msgContentSb.lastIndexOf("&"));
        }

        LogUtil.d("actionUrl <<<  " + msgContentSb.toString());

        //创建RequestBody
        RequestBody body = builder.build();
        //创建Request
        final Request request = new Request.Builder().url(msgContentSb.toString()).post(body).build();
        //单独设置参数 比如读取超时时间
        final Call call = mClient.newBuilder().writeTimeout(50, TimeUnit.SECONDS).build().newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e(TAG, e.toString());
                LogUtil.d(TAG, "onFailure");
                deliverDataFailure(request, e, callBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                String resultEn = response.body().string();
                LogUtil.d(TAG, "result>>>" + resultEn);
                try {
                    String result = EncryptUtil.getInstance().getDecryptData(resultEn);
                    LogUtil.d(TAG, "result>>>" + result);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                deliverDataSuccess(resultEn, callBack);

//                if (response.isSuccessful()) {
//                    String string = response.body().string();
//                    Log.e(TAG, "response ----->" + string);
//
//                } else {
//                }
            }
        });


    }

    public static RequestBody createCustomRequestBody(final MediaType contentType, final File file, final
    ProgressListener listener) {
        return new RequestBody() {
            @Override
            public MediaType contentType() {
                return contentType;
            }

            @Override
            public long contentLength() {
                return file.length();
            }

            @Override
            public void writeTo(BufferedSink sink) throws IOException {
                Source source;
                try {
                    source = Okio.source(file);
                    //sink.writeAll(source);
                    Buffer buf = new Buffer();
                    Long remaining = contentLength();
                    for (long readCount; (readCount = source.read(buf, 2048)) != -1; ) {
                        sink.write(buf, readCount);
                        listener.onProgress(contentLength(), remaining -= readCount, remaining == 0);

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
    }

    public interface ProgressListener {
        void onProgress(long totalBytes, long remainingBytes, boolean done);
    }

    public interface IFileDownload {
        void beforeDown();

        void downing(float complete);

        void downFinish();

        void downError();
    }

    public void getHtml(final Context mContext, final String url, final String fileName, final IFileDownload
            callback) {
        if (callback != null)
            callback.beforeDown();
        OkHttpManager.getInstance().downloadFile(url)
                .subscribeOn(Schedulers.io())
                .doOnNext(new Action1<Response>() {
                    @Override
                    public void call(Response response) {
                        //保存到文件中
                        try {
                            FileOutputStream fileOutputStream = mContext.openFileOutput(fileName, MODE_PRIVATE);
                            byte[] bytes = new byte[2048];
                            long totalSize = response.body().contentLength();
                            InputStream inputStream = response.body().byteStream();
                            //循环读取数据
                            int len;
                            int number = 0;
                            while ((len = inputStream.read(bytes)) != -1) {
                                number++;
                                float complete = number * 2048.0f / totalSize;
//                                LogUtil.d(complete + "");
                                if (callback != null)
                                    callback.downing(complete);
                                fileOutputStream.write(bytes, 0, len);
                            }
                            fileOutputStream.flush();
                            fileOutputStream.flush();

                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                response.body().close();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Response>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        LogUtil.d(TAG, "wubaojie>>>onError: 主页下载失败");
                        if (callback != null)
                            callback.downError();
                    }

                    @Override
                    public void onNext(Response response) {
                        LogUtil.d(TAG, "wubaojie>>>call: 主页下载完成");
                        if (callback != null)
                            callback.downFinish();
                    }
                });
    }
}
